package com.example.csclient.ui.screens

import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.TimePickerState
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.APPLICATION_KEY
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import com.example.csclient.CscApplication
import com.example.csclient.data.CscRepository
import com.example.csclient.model.CscModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import java.io.IOException

data class CscUiState(
    val loginState: Boolean = false,
    val selectedOption: String = "停止充电",
    val chargeMode: String = "充电停止",
    val showReservation: Boolean = false,
    val showHandModelAdjust: Boolean = false,
    val loginPageResponse: String = "",
    val isInReservation: Boolean = false,
    val showRechargeDialog: Boolean = false
)

class CscViewModel(private val cscRepository: CscRepository) : ViewModel() {
    //val uiState by mutableStateOf(CscUiState())
    private val _cscUiState = MutableStateFlow(CscUiState())
    val cscUiState: StateFlow<CscUiState> = _cscUiState.asStateFlow()

    private val _appData = MutableStateFlow(CscModel())
    val appData: StateFlow<CscModel> = _appData.asStateFlow()

    fun handleSelectButtonClick(option: String) {
        _cscUiState.update { it.copy(selectedOption = option) }
        _cscUiState.update {
            it.copy(
                chargeMode = when (it.selectedOption) {
                    "快充模式" -> "快充中"
                    "慢充模式" -> "慢充中"
                    "智能充电" -> "智能充电中"
                    "手动模式" -> "手动调整充电模式"
                    "退出登陆" -> "退出登陆……"
                    else -> "充电停止"
                }
            )
        }
        if (_cscUiState.value.selectedOption == "手动模式") {
            _cscUiState.update { it.copy(showHandModelAdjust = true) }
        }
        val mode = "b=0.0,c=0.0,m=" + when (_cscUiState.value.selectedOption) {
            "快充模式" -> "f"
            "慢充模式" -> "s"
            "智能充电" -> "a"
            "手动模式" -> "h"
            "退出登陆" -> "e"
            else -> "n"
        }
        viewModelScope.launch {
            cscRepository.publishControlMessage(mode)
        }
    }

    fun handleRechargeRequest(rechargeMoney: Float) {
        _cscUiState.update { it.copy(showRechargeDialog = false) }

        val commands = "b=%.3f".format(rechargeMoney)
        viewModelScope.launch {
            cscRepository.publishControlMessage(commands)
        }
    }

    fun handleRechargeButtonPush() {
        _cscUiState.update { it.copy(showRechargeDialog = true) }
    }

    @OptIn(ExperimentalMaterial3Api::class)
    fun handleReservation(timePickerState: TimePickerState, willChargeAfterScheduleAttach: Boolean) {
        _cscUiState.update { it.copy(showReservation = false) }
        if (timePickerState.hour == 0 && timePickerState.minute == 0) {
            return
        }
        _cscUiState.update { it.copy(isInReservation = true) }
        val commands = "t=%02d:%02d,w=%d"
            .format(
                timePickerState.hour, timePickerState.minute,
                if (willChargeAfterScheduleAttach) 1 else 0
            )
        viewModelScope.launch {
            cscRepository.publishControlMessage(commands)
        }
    }

    fun handleHandModelAdjust(handModelPercent: Float, powerAdjustPercent: Float) {
        _cscUiState.update { it.copy(showHandModelAdjust = false) }
        if (handModelPercent == -1f) {
            return
        }
        val commands = "u=%.1f,c=%.4f"
            .format(powerAdjustPercent, handModelPercent)
        viewModelScope.launch {
            cscRepository.publishControlMessage(commands)
        }
    }

    fun handleCancelReservation() {
        val commands = "t=00:00"
        viewModelScope.launch {
            cscRepository.publishControlMessage(commands)
        }
    }

    /* 用户登陆，并连接到指定的充电桩 */
    fun handleConnectEmbeddedDevice(userName: String, password: String, deviceID: String) {
        if (_cscUiState.value.loginState) {
            return
        }
        viewModelScope.launch {
            try {
                cscRepository.subscribeDevice(
                    userName, password, deviceID
                ) { result ->
                    if (result != "success") {
                        _cscUiState.update { it.copy(loginPageResponse = result) }
                        return@subscribeDevice
                    }
                    /* 从登陆界面转到主页面 */
                    _cscUiState.update { it.copy(loginState = true) }
                    //
                    cscRepository.setDefaultHandler { message ->
                        handlerSubscribeMessage(message)
                    }
                }
            } catch (_: IOException) {
                _cscUiState.update { it.copy(loginPageResponse = "网络不可达，请检查网络") }
            }
        }
    }

    private fun makeMessagePack(message: String): HashMap<String, String> {
        val messageMap = HashMap<String, String>()
        val tokens: List<String> = message.split(',')
        for (token in tokens) {
            val keyValue = token.split('=')
            if (keyValue.size != 2) {
                continue
            }
            messageMap[keyValue[0]] = keyValue[1]
        }
        return messageMap
    }

    private fun setProgress(progress: String?) {
        if (progress == null) {
            return
        }
        _appData.update {
            it.copy(
                chargePercent = try {
                    progress.toFloat().coerceAtLeast(0f).coerceAtMost(1f)
                } catch (_: NumberFormatException) {
                    0f
                }
            )
        }
    }

    private fun setPower(power: String?) {
        if (power == null) {
            return
        }
        _appData.update {
            it.copy(
                chargePower = try {
                    power.toFloat().coerceAtLeast(0f)
                } catch (_: NumberFormatException) {
                    0f
                }
            )
        }
    }

    private fun setVoltage(voltage: String?) {
        if (voltage == null) {
            return
        }
        _appData.update {
            it.copy(
                chargeVoltage = try {
                    voltage.toFloat().coerceAtLeast(0f)
                } catch (_: NumberFormatException) {
                    0f
                }
            )
        }
    }

    private fun setTemp(temp: String?) {
        if (temp == null) {
            return
        }
        _appData.update {
            it.copy(
                chargeTemp = try {
                    temp.toFloat().coerceAtLeast(-30f).coerceAtMost(120f)
                } catch (_: NumberFormatException) {
                    0f
                }
            )
        }
    }

    private fun setBalance(balance: String?) {
        if (balance == null) {
            return
        }
        _appData.update {
            it.copy(
                chargeBalance = try {
                    balance.toFloat().coerceAtLeast(0f)
                } catch (_: NumberFormatException) {
                    0f
                }
            )
        }
    }

    private fun setChargeTime(chargedTime: String?) {
        if (chargedTime == null) {
            return
        }
        _appData.update { it.copy(chargedTime = chargedTime) }
    }

    private fun setReservationTime(reservationTime: String?) {
        if (reservationTime == null) {
            return
        }
        _appData.update { it.copy(reservationTime = reservationTime) }
    }

    private fun setIsInReservation(isInReservation: String?) {
        if (isInReservation == null) {
            return
        }
        _cscUiState.update { it.copy(isInReservation = isInReservation == "1") }
    }

    private fun setChargeModeSet(modeSet: String?) {
        if (modeSet == null) {
            return
        }

        _cscUiState.update {
            it.copy(
                selectedOption = when (modeSet) {
                    "f" -> "快充模式"
                    "s" -> "慢充模式"
                    "a" -> "智能充电"
                    "h" -> "手动模式"
                    else -> "无充电模式"
                },
                chargeMode = when (modeSet) {
                    "f" -> "快充中"
                    "s" -> "慢充中"
                    "a" -> "智能充电中"
                    "h" -> "手动调整充电模式"
                    else -> "无充电模式"
                }
            )
        }

        _cscUiState.update {
            it.copy(
                chargeMode = when (it.selectedOption) {
                    "快充模式" -> "快充中"
                    "慢充模式" -> "慢充中"
                    "智能充电" -> "智能充电中"
                    "手动模式" -> "手动调整充电模式"
                    else -> "充电停止"
                }
            )
        }
        //if (_cscUiState.value.selectedOption == "手动模式") {
            //_cscUiState.update { it.copy(showHandModelAdjust = true) }
        //}
        val mode = "b=0.0,c=0.0,m=" + when (_cscUiState.value.selectedOption) {
            "快充模式" -> "f"
            "慢充模式" -> "s"
            "智能充电" -> "a"
            "手动模式" -> "h"
            else -> "n"
        }
        viewModelScope.launch {
            cscRepository.publishControlMessage(mode)
        }
    }

    private fun handleLogout(message: String?) : Boolean {
        if (message == null || message != "y") {
            return false
        }

        /* 重置为登陆界面 */
        _cscUiState.update { it.copy(loginState = false) }
        return true
    }

    /* 处理服务器返回的信息 */
    private fun handlerSubscribeMessage(message: String) {
        if (message == "ErrorNetwork") {
            _cscUiState.update {
                it.copy(
                    loginPageResponse = "网络断连，请尝试重新连接",
                    loginState = false
                )
            }
            return
        }
        val messageMap = makeMessagePack(message)
        if (handleLogout(messageMap["logout"])) {
            return
        }
        setProgress(messageMap["progress"])
        setPower(messageMap["power"])
        setVoltage(messageMap["voltage"])
        setTemp(messageMap["temp"])
        setBalance(messageMap["balance"])
        setChargeTime(messageMap["ctime"])
        setReservationTime(messageMap["restime"])
        setIsInReservation(messageMap["inrev"])
        setChargeModeSet(messageMap["mode"])
    }

    /* 用户注册方法 */
    fun handleRegisterUser(userName: String, password: String) {
        viewModelScope.launch {
            try {
                cscRepository.registerUser(userName, password) { result ->
                    if (result == "success") {
                        _cscUiState.update { it.copy(loginPageResponse = "注册成功！请登陆") }
                        /* 将正确的用户名和密码添加到 Repo 的信息当中 */
                        cscRepository.setRepoInfo(userName, password)
                    } else {
                        _cscUiState.update { it.copy(loginPageResponse = result) }
                    }
                }
            } catch (_: IOException) {
                _cscUiState.update { it.copy(loginPageResponse = "网络不可达，请检查网络") }
            }
        }
    }

    fun willShowReservation(showReservation: Boolean) {
        _cscUiState.update { it.copy(showReservation = showReservation) }
    }

    /**
     * Factory for [CscViewModel] that takes [CscRepository] as a dependency
     */
    companion object {
        val Factory: ViewModelProvider.Factory = viewModelFactory {
            initializer {
                val application = (this[APPLICATION_KEY] as CscApplication)
                val cscRepository = application.container.cscRepository
                CscViewModel(cscRepository = cscRepository)
            }
        }
    }
}